package mm.util;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

// key mustn't contains '.'
public class I18NMap extends HashMap<String, Object> {

	private static final long serialVersionUID = 1L;
	private static final Map<Locale, I18NMap> I18NMAPS = new HashMap<Locale, I18NMap>();
	
	@SuppressWarnings("unchecked")
	private I18NMap(Locale locale){
		Properties properties=new Properties();
		try {
			properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("i18n/"+locale+".properties"));
		} catch (Exception e) {
			LOG.error("Locale file "+locale.getLanguage()+" not found!", e);
			return;
		}
		for(Object keyO : properties.keySet()){
			String key=(String)keyO;
			String value=properties.getProperty(key);
			if(key.contains(".")){
				LOG.error("Locale key can't include '.'! ("+key+")");
				continue;
			}else if(key.matches("^[^\\[\\]]+\\[[^\\[\\]]+\\]$")){
				String subMapName=key.substring(0, key.indexOf("["));
				String subMapKey=key.substring(key.indexOf("[")+1, key.length()-1);
				Object existingSubMapO=super.get(subMapName);
				if(existingSubMapO==null||!(existingSubMapO instanceof Map)){
					existingSubMapO=new HashMap();
					this.put(subMapName, existingSubMapO);
				}
				Map existingSubMap=(Map)existingSubMapO;
				Locale matchedLocale=findLocaleByLanguage(Constants.LOCALES.barMap().keySet(), subMapKey);
				if(matchedLocale!=null){
					existingSubMap.put(matchedLocale, value);
				}else{
					existingSubMap.put(subMapKey, value);
				}
			}else{
				this.put(key, value);
			}
		}
		if(!Constants.DEFAULT_LOCALE.toString().equals(locale.toString())){
			I18NMap defaultMap = getInstance(Constants.DEFAULT_LOCALE);
			for (String defaultKey : defaultMap.keySet()) {
				Object defaultValue = defaultMap.get(defaultKey);
				if(defaultValue!=null){
					if(super.get(defaultKey)==null){
						super.put(defaultKey, defaultValue);
					}else if(defaultValue instanceof Map){
						if(!(super.get(defaultKey) instanceof Map)){
							super.put(defaultKey, defaultValue);
						}else{
							Map subMap=(Map)super.get(defaultKey);
							Map defaultSubMap=(Map)defaultValue;
							for (Object defaultSubKey : defaultSubMap.keySet()) {
								Object defaultSubValue=defaultSubMap.get(defaultSubKey);
								if(defaultSubValue!=null){
									if(subMap.get(defaultSubKey)==null){
										subMap.put(defaultSubKey, defaultSubValue);
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	public static I18NMap getInstance(Locale locale){
		return I18NMAPS.get(locale);
	}
	
	public static void initInstances(){
		I18NMAPS.put(Constants.DEFAULT_LOCALE, new I18NMap(Constants.DEFAULT_LOCALE));
		for(Locale locale : Constants.LOCALES.barMap().keySet()){
			if(!Constants.DEFAULT_LOCALE.toString().equals(locale.toString()))
				I18NMAPS.put(locale, new I18NMap(locale));
		}
	}
	
	public static Locale findLocaleByLanguage(Set<Locale> locales, String localeLanguage){
		for(Locale locale : locales){
			if(locale.toString().equals(localeLanguage)){
				return locale;
			}
		}
		return null;
	}

	@Override
	public Object get(Object key) {
		if(key==null){
			return "";
		}
		Object value = super.get(key);
//		if(value==null){
//			I18NMap defaultMap = getInstance(Constants.DEFAULT_LOCALE);
//			value=defaultMap.get(key);
//		}
		if(value==null){
			value=key;
		}
		return value;
	}

}
